/*
   FieldVis - A Tool for Visualizing Astrophysical Magnetohydrodynamic Flow
   
   Copyright (C) 2006 - 2008     FieldVis Development Team
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
  
   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

   File     : ColorMap.cpp
   Author   : Blayne Field
   
   Purpose  : Implementation file for the ColorMap class.  This class is for
              mapping colors based on some set of values
*/

#include "ColorMap.h"


ColorMap::ColorMap(const std::string &fileName)
   : colorField(NULL), minValue(0.0), maxValue(0.0)
{
   LoadFile(fileName);
}


ColorMap::~ColorMap()
{
   if (UsingField())
   {
      delete colorField;
   }
}


void ColorMap::AssociateField(const std::string &fileName,
                              const int x, const int y, const int z,
                              const float min, const float max)
{
   colorField = new ScalarField(fileName, x, y, z);

   minValue = min;
   maxValue = max;
}


void ColorMap::LoadFile(const std::string &fileName)
{
   int valueCount = 0;

   // open up the file and read in the colors
   std::ifstream inFile(fileName.c_str());
   int r, g, b;

   while (!inFile.eof())
   {
      inFile >> r >> g >> b;
      if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255)
      {
         std::cerr << "WARNING: Invalid color value specified around line " 
                   << valueCount << " of " << fileName << ", discarding value"
                   << std::endl;
      }
      else
      {
         colors.push_back(Vector3D(r / 255.0, g / 255.0, b / 255.0));
         valueCount++;
      }
   }
}


void ColorMap::DrawColorMap(int xStart, int yStart, int width, int height, TextWriter *writer)
{
   std::stringstream minStringStream;
   minStringStream << "min:" << minValue;
   std::string minString;
   minStringStream >> minString;
   std::stringstream maxStringStream;
   maxStringStream << "max:" << maxValue;
   std::string maxString;
   maxStringStream >> maxString;

   glColor4f(1,1,1,1);
   writer->DrawText(xStart, yStart, minString, LEFT_JUST);
   writer->DrawText(xStart + width, yStart, maxString, RIGHT_JUST);

   glDisable(GL_TEXTURE_2D);
   glDisable(GL_LIGHTING);
   for (int x = 0; x < width; x++)
   {
      int index = (x * colors.size()) / width;
      glColor4f(colors[index].GetX(), colors[index].GetY(), colors[index].GetZ(), 1);
      glBegin(GL_LINES);
      glVertex2d(xStart + x, yStart + writer->GetCharHeight());
      glVertex2d(xStart + x, yStart + height);
      glEnd();
   }
   glEnable(GL_LIGHTING);
   glEnable(GL_TEXTURE_2D);
}


Vector3D ColorMap::GetRGBValue(Point &p) const
{
   if (UsingField())
   {
      Point p1 = p * colorField->GetScaleFactor();
      float valueAtPoint = colorField->GetInterpolatedValue(p1);
      int index = (int) 
                  ((colors.size() * (valueAtPoint - minValue)) /  (maxValue - minValue));

      if (valueAtPoint >= maxValue)
         return colors[colors.size() - 1];
      else if (valueAtPoint <= minValue)
         return colors[0];
      else
         return colors[index];
   }
   else
   {
      return colors[0];
   }
}

